#include "linkseditordialog.h"

#include <idocument.h>

#include <QtGui/QFrame>
#include <QtGui/QGridLayout>
#include <QtGui/QLabel>
#include <QtGui/QListView>
#include <QtGui/QPushButton>
#include <QtGui/QStandardItemModel>

using namespace core;
using namespace gui;

typedef QSharedPointer<IDocument> Document;

LinksEditorDialog::LinksEditorDialog(
    const QList<QSharedPointer<IDocument> >& canBeAdded,
    const QList<QSharedPointer<IDocument> >& canBeRemoved,
    QWidget* parent, bool singleLinkMode) : QDialog(parent),
        m_singleLinkMode(singleLinkMode),
        m_okButton(0),
        m_cancelButton(0),
        m_addButton(0),
        m_removeButton(0),
        m_canBeAddedView(0),
        m_canBeRemovedView(0),
        m_canBeAddedModel(new QStandardItemModel()),
        m_canBeRemovedModel(new QStandardItemModel()),
        m_added(),
        m_removed(),
        m_canBeAdded(canBeAdded),
        m_canBeRemoved(canBeRemoved)
{
    createLayout();
    connectSlots();
    initModels();
    ensureSelected();

    checkButtons();

    setWindowTitle(m_singleLinkMode ? tr("Set link") : tr("Add/Remove links"));
}

LinksEditorDialog::~LinksEditorDialog()
{

}

QList<QSharedPointer<IDocument> > LinksEditorDialog::added() const
{
    return m_added;
}

QList<QSharedPointer<IDocument> > LinksEditorDialog::removed() const
{
    return m_removed;
}

void LinksEditorDialog::initModels()
{
    foreach (const Document& document, m_canBeAdded)
    {
        QStandardItem* item = new QStandardItem(document->name());
        item->setEditable(false);
        item->setData(QVariant::fromValue(document));
        m_canBeAddedModel->appendRow(item);
    }

    foreach (const Document& document, m_canBeRemoved)
    {
        QStandardItem* item = new QStandardItem(document->name());
        item->setEditable(false);
        item->setData(QVariant::fromValue(document));
        m_canBeRemovedModel->appendRow(item);
    }
}

void LinksEditorDialog::createLayout()
{
    QFrame* contentWrapper = new QFrame();
    QFrame* buttonsWrapper = new QFrame();

    QGridLayout* contentLayout = new QGridLayout();

    m_canBeAddedView = new QListView();
    m_canBeAddedView->setModel(m_canBeAddedModel);
    m_canBeRemovedView = new QListView();
    m_canBeRemovedView->setModel(m_canBeRemovedModel);

    m_addButton = new QPushButton(tr(">>"));
    m_addButton->setEnabled(false);
    m_removeButton = new QPushButton(tr("<<"));
    m_removeButton->setEnabled(false);

    contentLayout->addWidget(new QLabel(tr("Possible links")), 0, 0);
    contentLayout->addWidget(new QLabel(tr("Linked documents")), 0, 2);

    contentLayout->addWidget(m_canBeAddedView, 1, 0, 4, 1);
    contentLayout->addWidget(m_canBeRemovedView, 1, 2, 4, 1);

    contentLayout->addWidget(m_addButton, 2, 1, 1, 1);
    contentLayout->addWidget(m_removeButton, 3, 1, 1, 1);

    contentLayout->setRowStretch(1, 1);
    contentLayout->setRowStretch(2, 1);
    contentLayout->setRowStretch(3, 1);
    contentLayout->setRowStretch(4, 1);

    contentWrapper->setLayout(contentLayout);

    QVBoxLayout* mainLayout = new QVBoxLayout();

    mainLayout->addWidget(contentWrapper, 1);
    mainLayout->addWidget(buttonsWrapper);

    setLayout(mainLayout);

    m_okButton = new QPushButton(tr("OK"));
    m_okButton->setDefault(true);
    m_okButton->setEnabled(!m_singleLinkMode);
    m_cancelButton = new QPushButton(tr("Cancel"));

    QHBoxLayout* buttonsLayout = new QHBoxLayout();

    buttonsLayout->addWidget(m_okButton);
    buttonsLayout->addWidget(m_cancelButton);
    buttonsLayout->addStretch();

    buttonsWrapper->setLayout(buttonsLayout);
}

void LinksEditorDialog::connectSlots()
{
    connect(m_okButton, SIGNAL(clicked()),
        this, SLOT(accept()));
    connect(m_cancelButton, SIGNAL(clicked()),
        this, SLOT(reject()));

    connect(m_addButton, SIGNAL(clicked()),
        this, SLOT(addSelected()));
    connect(m_removeButton, SIGNAL(clicked()),
        this, SLOT(removeSelected()));

    /*connect(m_canBeAddedView->selectionModel(),
        SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
        this, SLOT(checkAdd(QItemSelection, QItemSelection)));

    connect(m_canBeRemovedView->selectionModel(),
        SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
        this, SLOT(checkRemove(QItemSelection, QItemSelection)));*/

    connect(m_canBeAddedModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
        this, SLOT(checkButtons()));
    connect(m_canBeAddedModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
        this, SLOT(checkButtons()));
    connect(m_canBeRemovedModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
        this, SLOT(checkButtons()));
    connect(m_canBeRemovedModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
        this, SLOT(checkButtons()));
}

void LinksEditorDialog::ensureSelected()
{
    QModelIndex index = m_canBeAddedModel->item(0) != 0 ?
        m_canBeAddedModel->item(0)->index() : QModelIndex();
    if (index.isValid())
    {
        m_canBeAddedView->selectionModel()->select(index,
            QItemSelectionModel::ClearAndSelect);
    }

    index = m_canBeRemovedModel->item(0) != 0 ?
        m_canBeRemovedModel->item(0)->index() : QModelIndex();

    if (index.isValid())
    {
        m_canBeRemovedView->selectionModel()->select(index,
            QItemSelectionModel::ClearAndSelect);
    }
}

// public slots
void LinksEditorDialog::accept()
{
    for (int i = 0; i < m_canBeAddedModel->rowCount(); ++i)
    {
        const QStandardItem* item = m_canBeAddedModel->item(i, 0);

        foreach (const Document& document, m_canBeRemoved)
        {
            const Document p = item->data(
                ).value<QSharedPointer<core::IDocument> >();
            if (document == p)
            {
                m_removed.append(document);
            }
        }
    }

    for (int i = 0; i < m_canBeRemovedModel->rowCount(); ++i)
    {
        const QStandardItem* item = m_canBeRemovedModel->item(i, 0);

        foreach (const Document& document, m_canBeAdded)
        {
            const Document p = item->data(
                ).value<QSharedPointer<core::IDocument> >();
            if (document == p)
            {
                m_added.append(document);
            }
        }
    }

    QDialog::accept();
}

// private slots
void LinksEditorDialog::addSelected()
{
    const QModelIndexList selected =
        m_canBeAddedView->selectionModel()->selectedRows();

    foreach (const QModelIndex& index, selected)
    {
        QStandardItem* item = m_canBeAddedModel->takeItem(index.row(),
            index.column());
        m_canBeAddedModel->removeRow(index.row());
        m_canBeRemovedModel->appendRow(item);
    }
}

void LinksEditorDialog::removeSelected()
{
    const QModelIndexList selected =
        m_canBeRemovedView->selectionModel()->selectedRows();

    foreach (const QModelIndex& index, selected)
    {
        QStandardItem* item = m_canBeRemovedModel->takeItem(index.row(),
            index.column());
        m_canBeRemovedModel->removeRow(index.row());
        m_canBeAddedModel->appendRow(item);
    }
}

void LinksEditorDialog::checkButtons()
{
    m_addButton->setEnabled((m_canBeAddedModel->rowCount() > 0) &&
        (m_singleLinkMode ?
            (m_canBeRemovedModel->rowCount() == 0 ? true : false)
            : true));

    if (m_singleLinkMode)
    {
        m_okButton->setEnabled(m_canBeRemovedModel->rowCount() > 0);
    }

    m_removeButton->setEnabled(m_canBeRemovedModel->rowCount() > 0);

    if (m_singleLinkMode)
    {
        m_okButton->setEnabled(m_canBeRemovedModel->rowCount() > 0);
    }
}


void LinksEditorDialog::checkAdd(const QItemSelection& selected,
    const QItemSelection& deselected)
{
    const QModelIndexList selectedIndexes = selected.indexes();

    bool valid = selectedIndexes.size() > 0;

    foreach(const QModelIndex& index, selectedIndexes)
    {
        valid = valid && index.isValid();
    }

    m_addButton->setEnabled(valid &&
        (m_singleLinkMode ?
            (m_canBeRemovedModel->rowCount() == 0 ? true : false)
            : true));
}

void LinksEditorDialog::checkRemove(const QItemSelection& selected,
    const QItemSelection& deselected)
{
    const QModelIndexList selectedIndexes = selected.indexes();

    bool valid = selectedIndexes.size() > 0;

    foreach(const QModelIndex& index, selectedIndexes)
    {
        valid = valid && index.isValid();
    }

    m_removeButton->setEnabled(valid);
}

